// 手写数字查看器
import React, { Component } from "react";
import "../App.css";
import { saveAs } from 'file-saver';

class HandWrittenBoard extends Component{

  constructor(props){
    super(props);

    this.state = {
      letterSize : props.size ?props.size :[32, 32],
      scale  : 10,
      width  : 1000,
      height : 1000,
      penSize : 32,
      penColor : '#ff0000'
    }

    this.handleValueChanged = this.handleValueChanged.bind(this);
    this.onMouseDown = this.onMouseDown.bind(this);
    this.onMouseMove = this.onMouseMove.bind(this);
    this.onMouseUp   = this.onMouseUp.bind(this);

    this.clear   = React.createRef();
    this.canvas  = React.createRef();
    this.thumbnail = React.createRef();
  }

  componentDidMount(){
    const letterSize = this.state.letterSize;

    const width   = this.state.scale * letterSize[0];
    const height  = this.state.scale * letterSize[1];

    this.setState({
      width  : width,
      height : height,
    });

    document.addEventListener('mousedown', this.onMouseDown, false);
    document.addEventListener('mousemove', this.onMouseMove, false);
    document.addEventListener('mouseup', this.onMouseUp, false);

    this.clearCanvas();
  }

  componentWillUnmount(){
    document.removeEventListener('mousedown', this.onMouseDown, false);
    document.removeEventListener('mousemove', this.onMouseMove, false);
    document.removeEventListener('mouseup', this.onMouseUp, false);
  }

  clearCanvas(){
    var canvas      = this.canvas.current; //document.getElementById('canvas');
    var ctx         = canvas.getContext('2d');
    const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    const data      = imageData.data;

    for (var i = 0; i < data.length; i += 4) {
        data[i]     = 255; // red
        data[i + 1] = 255; // green
        data[i + 2] = 255; // blue
        data[i + 3] = 255
    }
    // console.log(imageData)
    ctx.putImageData(imageData, 0, 0);
  }

  saveCanvas(){
    const imgVect = this.getImageData();
    const width = this.state.letterSize[0];
    const height = this.state.letterSize[1];
    let str = '';
    for(let h = 0; h < height; h++){
      for(let w = 0; w < width; w++){
        str += imgVect[h*width + w];
      }
      str += '\r\n';
    }
    // console.log(str);  
    let blob = new Blob([str], {type: "text/plain;charset=utf-8"});
    saveAs(blob, 'img.txt');
  }

  getPositionInCanvas(x, y){
    const canvas = this.canvas.current;
    if(!canvas) return;
    const offsetTop   = canvas.offsetTop;
    const offsetLeft  = canvas.offsetLeft;
    const width       = canvas.width;
    const height      = canvas.height;

    const px = x - (offsetLeft - window.scrollX);
    const py = y - (offsetTop - window.scrollY);

    if(px > 0 && px < width && py > 0 && py < height){
      return [px, py];
    }

    return undefined;
  }

  onMouseDown(event){
    const pos = this.getPositionInCanvas(event.x, event.y);
    if(!pos) return;
    // this.pickColor(pos[0], pos[1]);
    this.draw(pos[0], pos[1]);
    this.beginDraw = true;
  }

  onMouseMove(event){
    if(this.beginDraw){
      const pos = this.getPositionInCanvas(event.x, event.y);
      if(!pos) return;
      this.draw(pos[0], pos[1]);
    }else{
      this.beginDraw = false;
    }
  }

  pickColor(x, y){
    var canvas      = this.canvas.current; //document.getElementById('canvas');
    var ctx         = canvas.getContext('2d');
    const imageData = ctx.getImageData(x, y, 1, 1);
    const data      = imageData.data;

    console.log(data);
  }

  onMouseUp(){
    // 将图片转换为向量
    if(this.beginDraw){
      this.process();
      this.beginDraw = false;
    }

    this.beginDraw = false;
  }

  getBoxData(data, x, y, width, height){
    var sum = 0;
    for(let h = y; h < y + height; h++){
      for(let w = x; w < x + width; w++){      
        sum += data[h][w];
      }
    }
    return sum >= (width*height)/2 ? 1:0;
  }

  getImageData(){
    const canvas = this.canvas.current;
    var ctx         = canvas.getContext('2d');
    const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    const data      = imageData.data;
    // console.log(data);
    let mat = [];
    for(let h = 0; h < imageData.height; h++){
      mat[h] = [];
      for(let w = 0; w < imageData.width; w++){
        const i = (h * imageData.width + w) * 4;
        if(data[i] === 255 && data[i + 1] === 255 && data[i + 2] === 255){
          mat[h][w] = 0;
        }else{
          mat[h][w] = 1;
        }
      }
    }
    ctx.putImageData(imageData, 0, 0);
    // 缩放
    const scale = this.state.scale;
    const width = this.state.letterSize[0];
    const height = this.state.letterSize[1];
    let imgVector = [];
    for(let h = 0; h < height; h++){
      for(let w = 0; w < width; w++){
        imgVector.push(this.getBoxData(mat, w*scale, h*scale, scale, scale));
      }
    }
  
    return imgVector;
  }

  process(){
    const imgVector = this.getImageData();

    if(this.props.process){
      this.props.process(imgVector);
    }
  }

  draw(x, y){
    const penSize = this.state.penSize;
    const penColor = this.state.penColor;
    
    var canvas      = this.canvas.current; //document.getElementById('canvas');
    var ctx         = canvas.getContext('2d');
    const imageData = ctx.getImageData(x - penSize / 2, y - penSize / 2, penSize, penSize);
    const data      = imageData.data;

    for (var i = 0; i < data.length; i += 4) {
        data[i]     = parseInt('0x'+penColor.slice(1, 3)); // red
        data[i + 1] = parseInt('0x'+penColor.slice(3, 5)); // green
        data[i + 2] = parseInt('0x'+penColor.slice(5, 7)); // blue
        data[i + 3] = 255
    }
    // console.log(imageData)
    ctx.putImageData(imageData, x - penSize / 2, y - penSize / 2);
  }

  handleValueChanged(event){
    const id = event.target.id;
    const value = event.target.value;
    switch(id){
      case 'penSize':  if(value > 1 && value < Math.min(this.state.width/2, this.state.height/2)) this.setState({penSize:value});break;
      case 'penColor': this.setState({penColor:value});break;
      default:break;
    }
  }

  render(){
    return(
      <div>
        <button onClick={this.clearCanvas.bind(this)} ref={this.clear}>清空</button>
        <button onClick={this.saveCanvas.bind(this)} >保存</button>
        <button onClick={this.process.bind(this)} >处理</button>
        <div>
        <label>画笔大小:</label>
        <input type='number' id = 'penSize' value={this.state.penSize} onChange={this.handleValueChanged}></input>
        <label>画笔颜色:</label>
        <input type='color' id = 'penColor' value={this.state.penColor} onChange={this.handleValueChanged}></input>
        </div>
        <div className="div-flex-row">   
          <canvas ref={this.canvas}  style={{border:'1px solid red'}} width={this.state.width} height={this.state.height}></canvas>
          {/* <button ref={this.thumbnail} onClick={this.getImageData.bind(this)}>缩略图</button> */}
        </div>
      </div>
    );
  }
}

export default HandWrittenBoard;